package com.taxi.driver.module.order.ongoing;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.amap.api.maps.model.LatLng;
import com.qianxx.utils.PhoneUtils;
import com.qianxx.view.HeadView;
import com.taxi.driver.BuildConfig;
import com.taxi.driver.R;
import com.taxi.driver.common.AppConfig;
import com.taxi.driver.common.BaseFragment;
import com.taxi.driver.config.DriverType;
import com.taxi.driver.config.IConstants;
import com.taxi.driver.config.OrderStatus;
import com.taxi.driver.config.TimeType;
import com.taxi.driver.event.MapEvent;
import com.taxi.driver.module.amap.navi.SingleRouteCalculateActivity;
import com.taxi.driver.module.order.address.ChangeAddrActivity;
import com.taxi.driver.module.order.detail.OrderDetailActivity;
import com.taxi.driver.module.order.ongoing.dagger.DaggerOrderOngoingComponent;
import com.taxi.driver.module.order.ongoing.dagger.OrderOngoingModule;
import com.taxi.driver.module.order.price.PriceDetailActivity;
import com.taxi.driver.module.vo.AddressVO;
import com.taxi.driver.module.vo.OrderVO;
import com.taxi.driver.socket.SocketPushContent;
import com.taxi.driver.socket.SocketService;
import com.taxi.driver.util.Navigate;
import com.taxi.driver.util.ScreenUtil;
import com.taxi.driver.util.SpeechUtil;
import com.taxi.driver.widget.SlideView;
import com.taxi.driver.widget.TextViewPlus;
import com.taxi.driver.widget.dialog.ConfirmDialog;

import org.greenrobot.eventbus.EventBus;

import java.text.DecimalFormat;

import javax.inject.Inject;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

/**
 * 功能描述：行程中页面
 */
public class OrderOngoingFragment extends BaseFragment implements OrderOngoingContract.View {

    @BindView(R.id.slide_view)
    SlideView mSlideView;
    @BindView(R.id.head_view)
    HeadView mHeadView;
    @BindView(R.id.tv_top_start)
    TextViewPlus mTvTopStart;
    @BindView(R.id.tv_top_more)
    TextView mTvTopMore;
    @BindView(R.id.tv_navigate)
    TextViewPlus mTvNavigate;
    @BindView(R.id.tv_phone)
    TextViewPlus mTvPhone;
    @BindView(R.id.tv_left)
    TextView mTvLeft;
    @BindView(R.id.tv_right)
    TextView mTvRight;
    @BindView(R.id.layout_sub)
    LinearLayout mLayoutSub;
    @BindView(R.id.divider)
    View mDivider;
    @BindView(R.id.tv_price)
    TextView mTvPrice;
    @BindView(R.id.tv_emulator)
    Button mTvEmulator;
    @BindView(R.id.tv)
    TextView tv;
    @BindView(R.id.ll)
    LinearLayout ll;

    @Inject
    OrderOngoingPresenter mPresenter;

    private int mPreviousStatus; //旧的订单状态
    private double mTotalPrice; //临时记录价格(专车业务)
    private boolean mEmulator; //是否开启模拟导航
    private boolean mShowTraffic = true; //是否显示道路拥堵情况（默认开启）
    private String mOrderUuid;
    private LatLng mNaviTo; //导航的目标地点
    private AddressVO mChangedAddr; //改变的导航目标地点（坐标、具体地址）
    private ConfirmDialog reassignDialog;//订单被改派提示弹出

    public static OrderOngoingFragment newInstance(String orderUuid) {
        OrderOngoingFragment fragment = new OrderOngoingFragment();
        Bundle bundle = new Bundle();
        bundle.putString(IConstants.ORDER_UUID, orderUuid);
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        DaggerOrderOngoingComponent.builder()
                .appComponent(getAppComponent())
                .orderOngoingModule(new OrderOngoingModule(this))
                .build()
                .inject(this);
        mOrderUuid = getArguments().getString(IConstants.ORDER_UUID);
        mPresenter.setOrderUuid(mOrderUuid);
        mPresenter.onCreate();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mView = inflater.inflate(R.layout.fragment_order_ongoing, container, false);
        ButterKnife.bind(this, mView);

        // 滑动触发下一个状态
        mSlideView.setOnSlideListener(() -> mPresenter.switchToNextStatus());
        // HeadView 相关初始化
        mHeadView.setLeftVisibility(false);
        mHeadView.getRightTextView().setOnClickListener(v -> OrderDetailActivity.start(getActivity(), mOrderUuid,0));

        return mView;
    }

    @Override
    public void onResume() {
        super.onResume();
        mPresenter.subscribe();
        resetBtnDisplay();

        if (!ScreenUtil.isServiceWorked(getContext(), "com.taxi.driver.socket.SocketService")) {
            SocketService.startService(getContext());
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        mPresenter.unsubscribe();
    }

    @Override
    public void onStop() {
        super.onStop();

        if (ScreenUtil.isBackground(getActivity())) {
            SpeechUtil.speech(getActivity(), "您现在在服务中，进入后台超过5分钟可能会导致里程计价不准确，请及时回到应用");
            Intent intent = new Intent(getActivity(), OrderOngoingActivity.class);
            PendingIntent pi = PendingIntent.getActivity(getActivity(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
            Notification notification = new Notification.Builder(getActivity())
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentTitle("您现在在服务中，进入后台超过5分钟可能会导致里程计价不准确，请及时回到应用")
                    .setContentText("进入应用")
                    .setAutoCancel(true)
                    .setContentIntent(pi)
                    .build();
            NotificationManager manager = (NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
            manager.notify(10002, notification);
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mPresenter.onDestory();
    }

    @OnClick({R.id.tv_navigate, R.id.tv_phone, R.id.iv_traffic, R.id.iv_location, R.id.tv_top_start, R.id.tv_price, R.id.tv_emulator})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.tv_navigate: //跳转到独立的导航页
                skipToNavigate();
                break;
            case R.id.tv_phone://拨打号码
                PhoneUtils.skip(getContext(), mPresenter.getPassengerPhone());
                break;
            case R.id.iv_location: //定位
                EventBus.getDefault().post(new MapEvent(MapEvent.NAVI_LOCATE));
                break;
            case R.id.iv_traffic: //显示路况
                mShowTraffic = !mShowTraffic;
                EventBus.getDefault().post(new MapEvent(MapEvent.NAVI_TRAFFIC, mShowTraffic));
                break;
            case R.id.tv_top_start: //修改导航目的地
                ChangeAddrActivity.actionStart(getContext(), mPresenter.getNaviDest());
                break;
            case R.id.tv_price: //查看费用明细(专车)
                PriceDetailActivity.actionStart(getContext(), mOrderUuid, true, mTotalPrice);
                break;
            case R.id.tv_emulator: //模拟导航
                changeEmulator();
                break;
        }
    }

    /**
     * 设置界面显示
     *
     * @param vo
     */
    @Override
    public void setDisplay(OrderVO vo) {
        if (vo.subStatus == null) {
            toast("订单状态异常");
            return;
        }
        boolean showEndAddr = false; //是否显示目的地坐标
        boolean showNaviBtn = true;//是否显示导航按钮
        boolean showPos = true;//是否显示出发地/目的地
        boolean showMileage = true;//是否显示里程和预估时间
        String title = "";//标题文本
        String more = "";//标题下文本
        String btn = "";//滑动按钮文本
        int priceVis = View.GONE;
        LatLng naviTo; //导航目的地
        String phoneEnd;//联系电话
        if (!TextUtils.isEmpty(vo.actualPasMob))
            phoneEnd = vo.getActualPasMobEnd();//换乘车人电话
        else
            phoneEnd = vo.getPassengerPhoneEnd();//发单本人电话
        switch (vo.subStatus) {
            case OrderStatus.WAIT_ARRIVE_ORIGIN://司机已出发，但未到达"上车地点"
                if ( mPresenter.driverType() == DriverType.SPECIAL) {
                    title = "去接乘客";
                    btn = "到达上车地点";
                    more = TextUtils.isEmpty(phoneEnd) ? "去接乘客" : "去接乘客 尾号" + phoneEnd;
                }
                naviTo = vo.getOriginLatLng();//订单起点设为导航目的地
                break;
            case OrderStatus.WAIT_PASSENGER_GET_ON://司机已到达"上车地点"，但乘客未上车
                if ( mPresenter.driverType() == DriverType.SPECIAL) {
                    title = "等待中";
                    btn = "乘客已上车";
                    more = TextUtils.isEmpty(phoneEnd) ? "等待乘客" : "等待乘客 尾号" + phoneEnd + " 上车";
                }
                naviTo = vo.getOriginLatLng();//订单起点设为导航目的地
                if (AppConfig.isSpecial()) {//专车业务
                    priceVis = View.VISIBLE; //显示订单费用'
                }

                if (vo.typeTime == TimeType.DAILY_RENT ||
                        vo.typeTime == TimeType.HALF_DAY_RENT) {
                    showMileage = false;
                }
                break;
            case OrderStatus.DEPART://行程中(乘客已上车)
                if (mPresenter.driverType() == DriverType.SPECIAL) {
                    title = "行程中";
                    btn = "到达目的地";
                    more = TextUtils.isEmpty(phoneEnd) ? "去送乘客" : "去送乘客 尾号" + phoneEnd;
                }

                showEndAddr = true;
                naviTo = vo.getDestLatLng();//订单终点设为导航目的地
                if (AppConfig.isSpecial()) {//专车业务
                    priceVis = View.VISIBLE; //显示费用
                    //获得实时费用，关键是起步费和超时等待费
                    mPresenter.getRealtimeFare(mOrderUuid);
                }

                if (vo.typeTime == TimeType.DAILY_RENT ||
                        vo.typeTime == TimeType.HALF_DAY_RENT) {
                    showNaviBtn = false;
                    showPos = false;
                    showMileage = false;
                }

                if (BuildConfig.DEBUG)
                    showEmulatorBtn(); // TODO DEBUG版本下显示模拟导航按钮，便于测试
                break;
            default:
                OrderDetailActivity.start(getActivity(), mOrderUuid,0);
                getActivity().finish();
                return;
        }
        /* 订单状态改变，需要重置导航的目标地点和显示 */
        if (mPreviousStatus != vo.subStatus) {
            mChangedAddr = null;
        }

        mPreviousStatus = vo.subStatus;
        /* 如果有修改的导航地点，以设置的为准 */
        mNaviTo = mChangedAddr != null ? mChangedAddr.getLatLng() : naviTo;

        mHeadView.setTitle(title); //设置标题显示
        mTvTopStart.setSelected(showEndAddr); //设置图标显示
        mTvTopStart.setText(mChangedAddr != null
                ? mChangedAddr.getAddress() //如果有修改的导航地点，已设置的为准
                : (showEndAddr ? vo.destAddress : vo.originAddress));
        mTvTopMore.setText(more);

        mTvPrice.setVisibility(priceVis);

        mSlideView.setContent(btn); //按键内容
        mSlideView.resetView(); //重置按键显示
        mTvNavigate.setVisibility(showNaviBtn ? View.VISIBLE : View.GONE);//设置导航按钮的显示
        mTvTopStart.setVisibility(showPos ? View.VISIBLE : View.GONE);//设置出发地/目的地的显示
        mLayoutSub.setVisibility(showMileage ? View.VISIBLE : View.GONE);//设置里程和预估时间的显示

        if (vo.typeTime == TimeType.DAILY_RENT ||
                vo.typeTime == TimeType.HALF_DAY_RENT) {//订单类型是日租/半日租
            switch (vo.subStatus) {
                case OrderStatus.WAIT_ARRIVE_ORIGIN://司机未到达上车地点前，显示“订单起点”和“小车(司机当前位置)到订单起点之间的导航路线”
                    //设置是否记录导航位置变化
                    mPresenter.setIsDepart(vo.subStatus == OrderStatus.DEPART);
                    //设置导航路线的起终点
                    EventBus.getDefault().post(new MapEvent(MapEvent.NAVI_ORDER, mPresenter.getCurrentLatLng(), vo.getOriginLatLng()));
                    //开启导航
                    EventBus.getDefault().post(new MapEvent(MapEvent.NAVI_NAVIGATE, mNaviTo));
                    //显示订单起点
                    EventBus.getDefault().post(new MapEvent(MapEvent.MAP_SHOW_ORIGIN, vo.getOriginLatLng()));
                    break;
                case OrderStatus.WAIT_PASSENGER_GET_ON://司机到达上车地点但乘客未上车之前，只显示小车(司机当前位置)和订单起点
                    //开启巡航
                    EventBus.getDefault().post(new MapEvent(MapEvent.CRUISE, mPresenter.getCurrentLatLng()));
                    //显示订单起点
                    EventBus.getDefault().post(new MapEvent(MapEvent.MAP_SHOW_ORIGIN, vo.getOriginLatLng()));
                    break;
                case OrderStatus.DEPART://行程中(乘客已上车)，只显示小车(司机当前位置)
                    //开启巡航
                    EventBus.getDefault().post(new MapEvent(MapEvent.CRUISE, mPresenter.getCurrentLatLng()));
                    break;
            }
        } else {//预约单/即时单
            //设置是否记录导航位置变化
            switch (vo.subStatus) {
                case OrderStatus.WAIT_ARRIVE_ORIGIN:
                case OrderStatus.WAIT_PASSENGER_GET_ON://司机未接到乘客之前，都显示“订单起点”和“小车(司机当前位置)到订单起点之间的导航路线”
                    //设置导航路线的起终点
                    EventBus.getDefault().post(new MapEvent(MapEvent.NAVI_ORDER, mPresenter.getCurrentLatLng(), vo.getOriginLatLng()));
                    //开启导航
                    EventBus.getDefault().post(new MapEvent(MapEvent.NAVI_NAVIGATE, mNaviTo));
                    //显示订单起点
                    EventBus.getDefault().post(new MapEvent(MapEvent.MAP_SHOW_ORIGIN, vo.getOriginLatLng()));
                    break;
                default://行程中(乘客已上车)，显示“订单终点”和“小车(司机当前位置)到订单终点之间的导航路线”
                    //设置导航路线的起终点
                    EventBus.getDefault().post(new MapEvent(MapEvent.NAVI_ORDER, mPresenter.getCurrentLatLng(), vo.getDestLatLng()));
                    //开启导航
                    EventBus.getDefault().post(new MapEvent(MapEvent.NAVI_NAVIGATE, mNaviTo));
                    //显示订单终点
                    EventBus.getDefault().post(new MapEvent(MapEvent.MAP_SHOW_DEST, vo.getDestLatLng()));
                    break;
            }
        }
    }

    @Override
    public void resetBtnDisplay() {
        mSlideView.resetView(); //重置显示
    }

    /**
     * 跳转到订单详情页(优先从服务端获取数据)
     *
     * @param orderUuid
     */
    @Override
    public void arriveEnd(String orderUuid) {
        Navigate.openOrder(getContext(), orderUuid, true);
        getActivity().finish();
    }

    @Override
    public void showOrderPrice(double price) {
        mTvPrice.setText(String.format("%.01f", price) + "元");
    }

    /**
     * 实时显示当前剩余的里程和预估时间
     *
     * @param distance
     * @param time
     */
    @Override
    public void setNaviInfoDisplay(Integer distance, Integer time) {
        String strDistance = distance == null
                ? getResources().getString(R.string.order_navi_distance_calculating)
                : new DecimalFormat("#.##").format(distance * 1.0D / 1000) + "公里";
        mTvLeft.setText(strDistance);
        String strTime = time == null
                ? getResources().getString(R.string.order_navi_time_calculating)
                : getMinute(time) + "分钟";
        mTvRight.setText(strTime);
    }

    /**
     * 改变导航路线
     *
     * @param vo
     */
    @Override
    public void changeAddress(AddressVO vo) {
        if (vo.getLatLng() == null) return;
        mChangedAddr = vo;
        mTvTopStart.setText(mChangedAddr.getAddress());
        //改变导航目的地
        mNaviTo = mChangedAddr.getLatLng();
        //开启导航
        EventBus.getDefault().post(new MapEvent(MapEvent.NAVI_NAVIGATE, mNaviTo));
    }

    /**
     * 跳转导航页面
     */
    private void skipToNavigate() {
        LatLng currentLatLng = mPresenter.getCurrentLatLng();
        if (currentLatLng == null) {
            toast("未获取到您当前的坐标");
            return;
        }
        if (mNaviTo == null) {
            toast("未获取到导航目的地坐标");
            return;
        }
        SingleRouteCalculateActivity.actionStart(getContext(), currentLatLng, mNaviTo);
    }

    /**
     * 显示订单总价
     *
     * @param totalPrice
     */
    @Override
    public void setTotalPrice(double totalPrice) {
        mTotalPrice = totalPrice;
        mTvPrice.setText(String.format("%.01f", totalPrice) + "元");
    }

    /**
     * 显示模拟导航按钮
     */
    private void showEmulatorBtn() {
        mTvEmulator.setVisibility(View.VISIBLE);
    }

    /**
     * 隐藏模拟导航按钮
     */
    private void hideEmulatorBtn() {
        mTvEmulator.setVisibility(View.GONE);
    }

    private void changeEmulator() {
        if (BuildConfig.DEBUG) {
            mEmulator = !mEmulator;
            EventBus.getDefault().post(new MapEvent(MapEvent.NAVI_EMULATOR, mEmulator));
        } else {
            mEmulator = false;
        }
        int strRes = mEmulator ? R.string.navi_emulator_close : R.string.navi_emulator_open;
        mTvEmulator.setText(strRes);
    }

    /**
     * 显示当前已行驶里程
     *
     * @param mileage
     */
    @Override
    public void showMileage(double mileage) {
        tv.setVisibility(View.VISIBLE);
        tv.setText("行驶里程：" + mileage + "公里");
    }

    /**
     * 显示超时等待费
     *
     * @param waitFare
     */
    @Override
    public void showWaitFare(double waitFare) {
        mTvPrice.setText(String.format("%.01f", waitFare) + "元");
    }

    /**
     * 订单被改派提示弹窗
     *
     * @param push
     */
    @Override
    public void showReassignDialog(SocketPushContent push) {
        if (reassignDialog == null) {
            reassignDialog = new ConfirmDialog(getActivity(), push.data.title, push.data.content, "确认");
            reassignDialog.setConfirmClickListener(dialog -> {
                dialog.dismiss();
                getActivity().finish();
            });
            reassignDialog.show();
        }
    }

    @Override
    public void showReassignedDialog(String msg) {
        if (reassignDialog == null) {
            reassignDialog = new ConfirmDialog(getActivity(), msg, null, "确认");
            reassignDialog.setConfirmClickListener(dialog -> {
                dialog.dismiss();
                getActivity().finish();
            });
            reassignDialog.show();
        }
    }

    /**
     * 时间格式转换
     *
     * @param secTime
     * @return
     */
    private int getMinute(int secTime) {
        int minute = secTime / 60;
        if (secTime % 60 >= 30) minute += 1; //秒数多于30，分钟加1
        return minute;
    }
}
